package com.maxis;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.TreeMap;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.json.simple.JSONObject;
import org.json.simple.JSONValue;

import au.com.bytecode.opencsv.CSVReader;
import au.com.bytecode.opencsv.CSVWriter;

import com.classes.CaseOutlet;
import com.classes.Casemast;
import com.classes.CasemastFactory;
import com.classes.DBFactory;
import com.classes.MerchantFactory;
import com.classes.OutletFactory;

public class MaxisMPOS {
	private static final String CONFIG_FILE = "/maxis.properties";
	private static final java.util.Properties appCfg = new java.util.Properties();

	private String userId = "";
	private String userGroup = "";
	private String userCountryCode = "";
	private String delimiter = "";
	private String unreadPath = "";
	private String unzipFolder = "";
	private String successPath = "";
	private String errorPath = "";
	private String failPath = "";
	private String mapResponsePath = "";
	private String logPath = "";
	private String datalogs = "";

	private String transitionNA = "put up";
	private String transitionAT = "Start";

	//Store temporary main csv info
	private String csvResponseFile = "";
	private String maincsv_ordertype = "";
	private String maincsv_brnnum = "";
	private String maincsv_ebdordernum = "";
	private String maincsv_mfosqty = "";
	private String maincsv_zipname = "";
	private String maincsv_mbbmaprefnid = "";
	private String maincsv_refnum = "";
	private String maincsv_merchantid = "";

	private int count_authority, count_owners, count_merchant;
	private int col_authority, col_owners, col_merchant, col_trading, col_contact, col_email, col_tel, col_fax, col_license, col_state, col_issuer, col_expdate, col_vc_acc, col_vgiro, col_amex_acc, col_amexgiro, col_amexcode, col_phys1, col_phys2, col_phys3, col_phys4, col_phypcode, col_phycity, col_phyrcode,col_pays1, col_pays2, col_pays3, col_pays4, col_paypcode, col_paycity, col_payrcode, col_cors1, col_cors2, col_cors3, col_cors4, col_corpcode, col_corcity, col_corrcode, col_mdrd, col_mdrc, col_mdra, col_reqtype, col_orgcode, col_nou, col_rem;


	public static void main(String[] args) {

		MaxisMPOS fw = new MaxisMPOS();

		try {
			InputStream stream = MaxisMPOS.class.getResourceAsStream(CONFIG_FILE);
			if (stream != null){
				appCfg.load(stream);
			} else {
				System.out.println("MaxisMPOS Input Stream is NULL");
			}

		} catch (Exception e) {
			System.err.println("MaxisMPOS Error loading file " + CONFIG_FILE);
			System.err.println(e.getMessage());
			e.printStackTrace();
		}


		fw.userId = appCfg.getProperty("user_id");
		fw.userGroup = appCfg.getProperty("user_group");
		fw.userCountryCode = appCfg.getProperty("user_country_code");
		fw.delimiter = appCfg.getProperty("file_delimiter");
		fw.unreadPath = appCfg.getProperty("unread_path");
		fw.unzipFolder = appCfg.getProperty("unzip_path");
		fw.successPath = appCfg.getProperty("success_path");
		fw.failPath = appCfg.getProperty("fail_path");
		fw.errorPath = appCfg.getProperty("error_path");
		fw.logPath = appCfg.getProperty("log_path");
		fw.mapResponsePath = appCfg.getProperty("MapResponsePath");

		fw.transitionNA = appCfg.getProperty("transition_na");
		fw.transitionAT = appCfg.getProperty("transition_at");

		try {

			while(true){
				fw.startWork();
				//Thread.sleep(10000);
				break;
			}

		} catch(Exception e){
			e.printStackTrace();
		}
	}

	public void startWork() {
		String filePath = this.unreadPath;
		System.out.println("Reading UNREAD folder " + filePath);

		File rootDir = new File( filePath );
	    File[] fileList = rootDir.listFiles();

	    if (fileList == null) return;

	    for ( File f : fileList ) {
	    	String fileName = f.getName().toLowerCase();

	    	if(fileName.endsWith(".txt") && fileName.startsWith("ebd")){
	    		String[] arrcsvname = f.getName().split("\\.",-1);
	    		System.out.println("ARR CSV " + arrcsvname[0]);

	    		this.csvResponseFile = this.createResponseFolder() + "\\" + arrcsvname[0].replace("ebd_", "mbb_") + ".txt";

	    		String mainCsvStatus = this.readMainCsv(f.getAbsolutePath());
	    		this.moveAllFiles(filePath, mainCsvStatus);

	            this.csvResponseFile = "";
	    	}

	    }

	    //create log file after read all files
	    if(this.datalogs.length() > 0) {
	    	this.appendlogs(this.datalogs);
	    }

	    this.datalogs = "";

	}

	public void moveAllFiles( String filePath, String folder) {
		File rootDir = new File( filePath );
	    File[] fileList = rootDir.listFiles();

	    if (fileList == null) {
	    	return;
	    }

	    for ( File f : fileList ) {
	    	String fileName = f.getName().toLowerCase();

	    	if(fileName.endsWith(".txt") || fileName.endsWith(".zip")){
	    		this.moveFile(f, folder);
	            this.deleteFile(f);
	    	}
	    }
	}

	//Once csv detected from list file, start read main csv
	public String readMainCsv(String csvpath) {
		this.datalogs += "READ EBD Summary File START  "+ System.getProperty("line.separator");

		CSVReader csvFile = null;
		CSVWriter csvWriter = null;
		String[] dataArray = null;
		String readStatus = "";

		try {
			csvFile = CSVFactory.getReader(csvpath, this.delimiter.charAt(0));

			try {
				while ((dataArray = csvFile.readNext()) != null) {
					if(dataArray.length > 1){
						String zipName = dataArray[4].toString();
						String zipPath = this.unreadPath + zipName;

						File zipFile = new File(zipPath + "/");
						if (!zipFile.exists()) {
							this.datalogs += "READ EBD Summary File FAILED  "+ System.getProperty("line.separator");
							readStatus = "Failed";

							break;
						}
					}
				}
			} finally {
				csvFile.close();
			}
		} catch (Exception e){
			this.datalogs += "Error reading EBD Summary File:\n" + this.getExceptionAsString(e) + "\nError message end";
			readStatus = "Failed";
		}



		if(readStatus.equals("Failed") == false) {

			boolean ok = DBFactory.connect();
			if(ok == false){
				this.datalogs += DBFactory.getMessage() + System.getProperty("line.separator");
				readStatus = "Error";
			}
			else {

				if(DBFactory.startTrans()) {

					try {
						csvFile = CSVFactory.getReader(csvpath, this.delimiter.charAt(0));
						csvWriter = CSVFactory.getWriter(this.csvResponseFile, this.delimiter.charAt(0));

						boolean allDone = true;

						try {
							while ((dataArray = csvFile.readNext()) != null) {
								this.maincsv_ordertype = dataArray[0].toString().trim();
								this.maincsv_brnnum = dataArray[1].toString().trim();
								this.maincsv_ebdordernum = dataArray[2].toString().trim();
								this.maincsv_mfosqty = dataArray[3].toString().trim();
								this.maincsv_zipname = dataArray[4].toString().trim();
								this.maincsv_merchantid = dataArray[5].toString().trim();
								this.maincsv_mbbmaprefnid = dataArray[6].toString().trim();

								readStatus = "Error";

								if(this.maincsv_ordertype.equals("AT")){
									readStatus = this.checkCasemast(this.maincsv_mbbmaprefnid, this.maincsv_merchantid);
								}

								if(readStatus.equals("Failed")) {
									allDone = false;
									break;
								}

								if(dataArray[4].toString().toLowerCase().endsWith(".zip")){
									String tempFolder = dataArray[4].toString().replace(".zip", "");
									readStatus = this.unZipIt(this.unreadPath + dataArray[4].toString(), this.unzipFolder + "\\" + tempFolder);
								}


								if(readStatus.equals("Error")) {
									allDone = false;
									break;
								}


								//append each row response to csv for maxis reference
								String[] data = new String[10];

								data[0] = this.maincsv_ordertype;
								data[1] = this.maincsv_brnnum;
								data[2] = this.maincsv_ebdordernum;
								data[3] = this.maincsv_mfosqty;
								data[4] = this.maincsv_zipname;
								data[5] = this.maincsv_merchantid;
								data[6] = this.maincsv_mbbmaprefnid;
								data[7] = this.maincsv_refnum;
								data[8] = "0101";
								data[9] = "";

								csvWriter.writeNext(data);


								this.maincsv_ordertype = "";
								this.maincsv_brnnum = "";
								this.maincsv_ebdordernum = "";
								this.maincsv_mfosqty = "";
								this.maincsv_zipname = "";
								this.maincsv_mbbmaprefnid = "";
								this.maincsv_refnum = "";

							}
						} finally {
							csvFile.close();
							csvWriter.close();
						}

			        	if(allDone) {
			        		DBFactory.commitTrans();
			        	}
			        	else {
			        		this.datalogs += "Error processing EBD Summary File  "+ System.getProperty("line.separator");
			        		DBFactory.rollback();
			        	}

					} catch (Exception e) {
						this.datalogs += "Error processing EBD Summary File:\n" + this.getExceptionAsString(e) + "\nError message end";
						readStatus = "Error";
					}


				}

			}

        	DBFactory.close();
		}


		this.datalogs += "READ EBD Summary File END  "+ System.getProperty("line.separator");

    	return readStatus;
  }

  public String checkCasemast(String referenceNo, String mId){
	  this.datalogs += "CHECK CASEMAST START  "+ referenceNo + System.getProperty("line.separator");

	  String checkStatus = "Successful";

	  Casemast m_case = CasemastFactory.getCaseMastByRefNo(referenceNo);
	  if(m_case == null) {
	  	this.datalogs += CasemastFactory.getMessage() + System.getProperty("line.separator");
	  	checkStatus = "Failed";
	  }
	  else {
		  OutletFactory o = new OutletFactory();
		  ArrayList<CaseOutlet> c_outlets = o.getCaseOutlets((int) m_case.getId());
		  if(c_outlets == null) {
			  this.datalogs += o.getMessage() + System.getProperty("line.separator");
			  	checkStatus = "Failed";
		  }

		  if(c_outlets.size() <= 0) {
			  this.datalogs += "Outlets array is empty. " + System.getProperty("line.separator");
			  checkStatus = "Failed";
		  } else {
			  CaseOutlet c_outlet = o.getCaseOutlet((int) m_case.getId(), (int) c_outlets.get(0).getOutlet().getId());
			  if(c_outlet == null){
				  this.datalogs += "Outlet item is empty. " + System.getProperty("line.separator");
				  checkStatus = "Failed";
			  }

			  JSONObject obj = (JSONObject) JSONValue.parse(c_outlet.getOutlet().getMDRRate());
			  if(obj == null){
				  this.datalogs += "Outlet MDR detail is empty. " + System.getProperty("line.separator");
				  checkStatus = "Failed";
			  }
			  else {
				  String mid_pos = obj.get("14").toString().trim();
				  //String mid_amex = obj.get("283").toString().trim();

				  if(!mid_pos.equals(this.maincsv_merchantid)){
					  this.datalogs += "MID not found in MDR details. " + System.getProperty("line.separator");
					  checkStatus = "Failed";
				  }
			  }
		  }
	  }


	  return checkStatus;
  }

  //if zip file exist in main csv, unzip it to another temporary folder
  public String unZipIt(String zipFile, String unzipToFolder){
	  	this.datalogs += "UNZIP FILE START  "+ zipFile + System.getProperty("line.separator");

	  	byte[] buffer = new byte[1024];
	  	String readStatus = "Error";

	  	try{
			File folder = new File(unzipToFolder);
			if(!folder.exists()){
				folder.mkdir();
	       	}


	       	//get the zip file content
			ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
			File newFile = null;

			try {
				//get the zipped file list entry
				ZipEntry ze = zis.getNextEntry();

				while(ze != null) {
					String fileName = ze.getName();

					newFile = new File(unzipToFolder + File.separator + fileName);
					this.datalogs += "file unzip : "+ newFile.getAbsoluteFile() + System.getProperty("line.separator");

					//create all non exists folders, else you will hit FileNotFoundException for compressed folder
					new File(newFile.getParent()).mkdirs();

					FileOutputStream fos = new FileOutputStream(newFile);
					int len;

					while ((len = zis.read(buffer)) > 0) {
						fos.write(buffer, 0, len);
					}

					fos.close();


					ze = zis.getNextEntry();
				}
			} finally {
				zis.closeEntry();
				zis.close();
			}

	       	if(newFile != null) {
		       	String appInfoStatus = this.listUnzippedFile(newFile.getParent());

	       		if(appInfoStatus.equals("Failed")) {
		       		readStatus = "Error";
		       	}
		       	else {
		       		readStatus = appInfoStatus;
		       	}
	       	}

		}
		catch(Exception ex){
			this.datalogs += "Error on unzip file as follow: "+ System.getProperty("line.separator") + this.getExceptionAsString(ex) + System.getProperty("line.separator");
			readStatus = "Error";
		}


		this.datalogs += "Unzip END" + System.getProperty("line.separator");
		return readStatus;
	}


  	public String listUnzippedFile( String zipFileFolder ) {
  		this.datalogs = this.datalogs + "List Unzipped folder START  "+ System.getProperty("line.separator");

  		File rootDir = new File( zipFileFolder );
  		File[] fileList = rootDir.listFiles();

  		if (fileList == null) {
  			return "Failed";
  		}

  		String appInfoPath = "";
  		ArrayList<String> attachmentPath = new ArrayList<String>();

  		for ( File f : fileList ) {
  			if(f.getName().equals("appInfo.csv")){
  				appInfoPath = f.getAbsolutePath();
			}
  			else {
  				attachmentPath.add(f.getAbsolutePath());
  			}
  		}


  		String status = this.readAppInfo(appInfoPath, attachmentPath);
  		this.datalogs += "List unzipped folder END  "+ System.getProperty("line.separator");

  		return status;
	}


  	public String readAppInfo(String appInfoPath, ArrayList<String> attachmentPath){

  		String app_info_status = "Failed";

  		try {
  			CSVReader appInfoCsvFile = CSVFactory.getReader(appInfoPath, this.delimiter.charAt(0));
  			String[] dataArray;

			try {
				while ((dataArray = appInfoCsvFile.readNext()) != null) {
					TreeMap<String, String> appinfo = new TreeMap<String, String>();

					appinfo.put("esarefno", dataArray[0]);
					appinfo.put("resellerloc", dataArray[1]);
					appinfo.put("offcode", dataArray[2]);
					appinfo.put("apptype", dataArray[3]);
					appinfo.put("ownership", dataArray[4]);
					appinfo.put("regname", dataArray[5]);
					appinfo.put("regno", dataArray[6]);
					appinfo.put("naturebus", dataArray[7]);
					appinfo.put("noyears", dataArray[8]);

					col_authority = 10;
					count_authority = Integer.parseInt(dataArray[9]);

					//authority info loops
					for(int x=1; x<=count_authority; x++){
						appinfo.put("atitle" + x, dataArray[col_authority + x - 1]);
						appinfo.put("adesignation" + x, dataArray[col_authority + count_authority + x]);
						appinfo.put("adob" + x, dataArray[col_authority + (2 * count_authority) + 1 + x]);
						appinfo.put("aname" + x, dataArray[col_authority + (3 * count_authority) + 2 + x]);
						appinfo.put("aicp" + x, dataArray[col_authority + (4 * count_authority) + 3 + x]);
						appinfo.put("agender" + x, dataArray[col_authority + (5 * count_authority) + 4 + x]);
					}



					col_owners = col_authority + (6 * count_authority) + 6;
					count_owners = Integer.parseInt(dataArray[col_owners - 1]);

					//Owners info loops
					for(int x=1; x<=count_owners; x++){
						appinfo.put("fname" + x, dataArray[col_owners + x - 1]);
						appinfo.put("lname" + x, dataArray[col_owners + count_owners + x]);
						appinfo.put("oicp" + x, dataArray[col_owners + (2 * count_owners) + 1 + x]);
						appinfo.put("onat" + x, dataArray[col_owners + (3 * count_owners) + 2 + x]);
					}

					col_trading = col_owners + (4 * count_owners) + 4;
					appinfo.put("trading", dataArray[col_trading - 1]);

					col_contact = col_trading + 1;
					appinfo.put("contact", dataArray[col_contact - 1]);

					col_email = col_contact + 1;
					appinfo.put("email", dataArray[col_email - 1]);

					col_tel = col_email + 1;
					appinfo.put("tel", dataArray[col_tel - 1]);

					col_fax = col_tel + 1;
					appinfo.put("fax", dataArray[col_fax - 1]);

					col_license = col_fax + 1;
					appinfo.put("license", dataArray[col_license - 1]);

					col_state = col_license + 1;
					appinfo.put("state", dataArray[col_state - 1]);

					col_issuer = col_state + 1;
					appinfo.put("issuer", dataArray[col_issuer - 1]);

					col_expdate = col_issuer + 1;
					appinfo.put("expdate", dataArray[col_expdate-1]);

					col_vc_acc = col_expdate + 1;
					appinfo.put("vc_acc", dataArray[col_vc_acc - 1]);

					col_vgiro = col_vc_acc + 1;
					appinfo.put("vgiro", dataArray[col_vgiro - 1]);

					col_amex_acc = col_vgiro + 1;
					appinfo.put("amex_acc", dataArray[col_amex_acc - 1]);

					col_amexgiro = col_amex_acc + 1;
					appinfo.put("amex_giro", dataArray[col_amexgiro - 1]);

					col_amexcode = col_amexgiro + 1;
					appinfo.put("amex_code", dataArray[col_vc_acc - 1]);

					col_merchant = col_amexcode + 1;
					count_merchant = Integer.parseInt(dataArray[col_merchant - 1]);

					//Merchant portal services info loops
					for(int x=1; x<=count_merchant; x++){
						appinfo.put("merchantportal" + x, dataArray[col_merchant + x - 1]);
					}

					//physical address
					col_phys1 = col_merchant + count_merchant + 1;
					appinfo.put("phy_street1", dataArray[col_phys1 - 1]);

					col_phys2 = col_phys1 + 1;
					appinfo.put("phy_street2", dataArray[col_phys2 - 1]);

					col_phys3 = col_phys2 + 1;
					appinfo.put("phy_street3", dataArray[col_phys3 - 1]);

					col_phys4 = col_phys3 + 1;
					appinfo.put("phy_street4", dataArray[col_phys4 - 1]);

					col_phypcode =col_phys4 + 1;
					appinfo.put("phy_pcode", dataArray[col_phypcode - 1]);

					col_phycity = col_phypcode + 1;
					appinfo.put("phy_city", dataArray[col_phycity - 1]);

					col_phyrcode = col_phycity + 1;
					appinfo.put("phy_rcode", dataArray[col_phyrcode - 1]);

					col_pays1 = col_phyrcode + 1;
					appinfo.put("pay_street1", dataArray[col_pays1 - 1]);

					//payment address
					col_pays2 = col_pays1 + 1;
					appinfo.put("pay_street2", dataArray[col_pays2 - 1]);

					col_pays3 = col_pays2 + 1;
					appinfo.put("pay_street3", dataArray[col_pays3 - 1]);

					col_pays4 = col_pays3 + 1;
					appinfo.put("pay_street4", dataArray[col_pays4 - 1]);

					col_paypcode = col_pays4 + 1;
					appinfo.put("pay_pcode", dataArray[col_paypcode - 1]);

					col_paycity = col_paypcode + 1;
					appinfo.put("pay_city", dataArray[col_paycity - 1]);

					col_payrcode = col_paycity + 1;
					appinfo.put("pay_rcode", dataArray[col_payrcode - 1]);

					//correspondence address
					col_cors1 = col_payrcode + 1;
					appinfo.put("cor_street1", dataArray[col_cors1 - 1]);

					col_cors2 = col_cors1 + 1;
					appinfo.put("cor_street2", dataArray[col_cors2 - 1]);

					col_cors3 = col_cors2 + 1;
					appinfo.put("cor_street3", dataArray[col_cors3 - 1]);

					col_cors4 = col_cors3 + 1;
					appinfo.put("cor_street4", dataArray[col_cors4 - 1]);

					col_corpcode = col_cors4 + 1;
					appinfo.put("cor_pcode", dataArray[col_corpcode - 1]);

					col_corcity = col_corpcode + 1;
					appinfo.put("cor_city", dataArray[col_corcity - 1]);

					col_corrcode = col_corcity + 1;
					appinfo.put("cor_rcode", dataArray[col_corrcode - 1]);

					col_mdrd = col_corrcode + 1;
					appinfo.put("mdr_debit", dataArray[col_mdrd - 1]);

					col_mdrc=col_mdrd+1;
					appinfo.put("mdr_credit", dataArray[col_mdrc-1]);

					col_mdra = col_mdrc + 1;
					appinfo.put("mdr_amex", dataArray[col_mdra - 1]);

					col_reqtype = col_mdra + 1;
					appinfo.put("req_type", dataArray[col_reqtype - 1]);

					col_orgcode = col_reqtype + 1;
					appinfo.put("org_code", dataArray[col_orgcode - 1]);

					col_nou = col_orgcode + 1;
					appinfo.put("no_of_unit", dataArray[col_nou - 1]);

					col_rem = col_nou + 1;
					appinfo.put("remark", dataArray[col_rem - 1]);


					app_info_status = this.create_business_detail(appinfo, attachmentPath);
				}
			} finally {
				appInfoCsvFile.close();
			}

  		}
  		catch (Exception e) {
  			this.datalogs += "Exception : " + System.getProperty("line.separator") + this.getExceptionAsString(e) + System.getProperty("line.separator");
  		}


  		return app_info_status;
  	}


  	public String create_business_detail(TreeMap<String, String> appinfo, ArrayList<String> attachmentPath){
		String mcc_code = "0000";
		String app_info_status="";
		String match_trace_status="";
		String outlet_detail_status="";
		List<String> amex_data = new ArrayList<String>();

		for(int x=1; x<=2; x++){
			JSONObject obj= new JSONObject();

			if(x <= count_authority){
				obj.put("title", appinfo.get("atitle"+x));
				obj.put("name", appinfo.get("aname"+x));
				obj.put("designation", appinfo.get("adesigntion"+x));
				obj.put("ic_no", appinfo.get("aicp"+x));
				obj.put("date_of_birth", appinfo.get("adob"+x));
				obj.put("gender", appinfo.get("agender"+x));
			}
			else {
				obj.put("title", "");
				obj.put("name", "");
				obj.put("designation", "");
				obj.put("ic_no", "");
				obj.put("date_of_birth", "");
				obj.put("gender", "");
			}

			amex_data.add(obj.toJSONString());
		}


		TreeMap<String, String> post = new TreeMap<String, String>();
		String ref_no_suffix = "";

		if(this.maincsv_ordertype.equals("AT")){
			post.put("app_type", "Additional Terminal/mPOS Reader");
			ref_no_suffix = "MXA";
		} else {
			post.put("app_type", "New Application");
			ref_no_suffix = "MXN";
		}

		post.put("ownership_status", appinfo.get("ownership"));
		post.put("registered_name", appinfo.get("regname"));
		post.put("registered_no", appinfo.get("regno"));
		post.put("nature_of_business", appinfo.get("naturebus"));
		post.put("mcc_code", mcc_code);
		post.put("paid_up_capital", "");
		post.put("recall_barcode_no", "");

		if( appinfo.get("noyears").equals("Less than 6 months")){
			post.put("years_in_business", "less_than_6m");
		} else if( appinfo.get("noyears").equals("More than 6 months")){
			post.put("years_in_business", "more_than_6m");
		} else if( appinfo.get("noyears").equals("1-3 Years")){
			post.put("years_in_business", "1y_to_3y");
		} else if( appinfo.get("noyears").equals("4-7 Years")){
			post.put("years_in_business", "4y_to_7y");
		} else if( appinfo.get("noyears").equals("8-10 Years")){
			post.put("years_in_business", "8y_to_10y");
		} else if( appinfo.get("noyears").equals("More than 10 Years")){
			post.put("years_in_business", "more_than_10y");
		} else {
			post.put("years_in_business", "");
		}

		post.put("avr_ticket_size", "");
		post.put("current_acquirer","");
		post.put("bank_name", "");
		post.put("current_acc_no", "");
		post.put("avr_monthly_deposit", "");
		post.put("monthly_deposit_entries", "[{\"month\":\"\",\"total_deposit\":\"\",\"balance\":\"\"},{\"month\":\"\",\"total_deposit\":\"\",\"balance\":\"\"},{\"month\":\"\",\"total_deposit\":\"\",\"balance\":\"\"}]");
		post.put("amex_auth_sign", amex_data.toString());
		post.put("reseller_location", appinfo.get("resellerloc"));
		post.put("ext_ref_no", this.maincsv_ebdordernum);
		post.put("last_ref_no", this.maincsv_mbbmaprefnid);
		post.put("gst_registration", "");
		post.put("rmcd_approval_no", "");

		String firstAction = this.transitionNA;
		if(this.maincsv_ordertype.equals("AT")){
			firstAction = this.transitionAT;
		}


		MerchantFactory m = new MerchantFactory();

		boolean ok = m.newMerchantCase(post, firstAction, this.userId, this.userGroup, this.userCountryCode, ref_no_suffix);
		if(ok == false){
			this.datalogs += m.getMessage() + System.getProperty("line.separator");
			app_info_status = "Failed";
		}
		else{
			Casemast c = CasemastFactory.getCaseMast(this.userGroup, m.getCaseID());
			if(c == null) {
				this.datalogs += CasemastFactory.getMessage() + System.getProperty("line.separator");
				app_info_status = "Failed";
			}
			else {
				this.datalogs += "created_map_ref_id #>>>># "+ c.getReferenceNo() + System.getProperty("line.separator");
				this.maincsv_refnum = c.getReferenceNo();

				app_info_status = "Success";

				this.datalogs += "Merchant created: #" + m.getMerchantID() + System.getProperty("line.separator");
				this.datalogs += "Case created: #"+ m.getCaseID() + System.getProperty("line.separator");
			}
		}


		if(m.getMerchantID() == 0 || m.getCaseID() == 0) {
			this.datalogs += "Fail to create business details:" + System.getProperty("line.separator");
			app_info_status = "Failed";
		}



		if(m.getMerchantID() != 0 && m.getCaseID() != 0) {
			for(String attachmentFile : attachmentPath) {
				try {
					File f = new File(attachmentFile);
					byte[] data = new byte[Integer.parseInt(Long.toString(f.length()))];

					FileInputStream r = new FileInputStream(attachmentFile);
					r.read(data);

					TreeMap<String, String> post2 = new TreeMap<String, String>();
					post2.put("file_name", f.getName());
					post2.put("file_type", "");
					post2.put("file_size", Long.toString(f.length()));
					post2.put("ref_no", "");

					ok = CasemastFactory.document_submit((int) m.getCaseID(), post2, data, this.userId);
					if(ok == false){
						this.datalogs += m.getMessage() + System.getProperty("line.separator");
						app_info_status="Failed";
					}
					else {
						System.out.println("attachment uploaded : "+ attachmentFile);
						this.datalogs += "Attachment uploaded: " + attachmentFile + System.getProperty("line.separator");
					}

				} catch (Exception e) {
					this.datalogs += e.getMessage() + System.getProperty("line.separator");
					app_info_status="Failed";
				}

			}


			match_trace_status = this.create_match_trace(appinfo, m.getMerchantID(), m.getCaseID());
			outlet_detail_status = this.create_outlet_detail(appinfo, mcc_code, m.getMerchantID(), m.getCaseID());

		}


		if(outlet_detail_status.equals("Success") && app_info_status.equals("Success") && match_trace_status.equals("Success")) {
			return "Success";
		} else {
			return "Failed";
		}
	}

	public String create_match_trace(TreeMap<String, String> appinfo,long mid, long cid){
		int merchant_id = (int) mid;
		int case_id = (int) cid;
		//int send_to_host = 1;

		String match_traces = "[";
		String match_sep = "";
		String match_trace_status="";

		for(int x=1; x<=count_owners; x++){
			String country_code = "";

			if(appinfo.get("onat" + x).toUpperCase().equals("MALAYSIA")){
				country_code = "MYS";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("AUSTRALIA")){
				country_code = "AUS";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("BRUNEI")){
				country_code = "BRN";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("CAMBODIA")){
				country_code = "KHM";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("CHINA")){
				country_code = "CHN";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("HONG KONG")){
				country_code = "HKG";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("INDIA")){
				country_code = "IND";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("INDONESIA")){
				country_code = "IDN";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("JAPAN")){
				country_code = "JPN";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("KOREA")){
				country_code = "KOR";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("MYANMAR")){
				country_code = "MMR";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("NEW ZEALAND")){
				country_code = "NZL";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("PAKISTAN")){
				country_code = "PAK";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("PHILIPPINES")){
				country_code = "PHL";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("PORTUGAL")){
				country_code = "PRT";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("SINGAPORE")){
				country_code = "SGP";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("SRI LANKA")){
				country_code = "LKA";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("TAIWAN")){
				country_code = "TWN";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("THAILAND")){
				country_code = "THA";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("UNITED KINGDOM")){
				country_code = "GBR";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("UNITED STATE")){
				country_code = "USA";
			}
			else if(appinfo.get("onat" + x).toUpperCase().equals("VIETNAM")){
				country_code = "VNM";
			}

			match_traces += match_sep + "{\"f_name\":\"" + appinfo.get("fname" + x) + "\",\"l_name\":\"" + appinfo.get("lname" + x) + "\",\"ic\":\"" + appinfo.get("oicp" + x) + "\",\"nationality\":\"" + country_code + "\",\"country_code\":\"" + country_code + "\"}";
			match_sep = ",";
		}

		match_traces += "]";

		TreeMap<String, String> post = new TreeMap<String, String>();

		if(this.maincsv_ordertype.equals("AT")){
			post.put("app_type", "Additional Terminal/mPOS Reader");
		} else {
			post.put("app_type", "New Application");
		}

		post.put("ownership_status",  appinfo.get("ownership"));
		post.put("match_trace", match_traces);

		MerchantFactory m = new MerchantFactory();

		boolean ok = m.editMerchantCase(merchant_id, case_id, post, this.userId);
		if(ok == false){
			this.datalogs = this.datalogs + m.getMessage() + System.getProperty("line.separator");
			match_trace_status="Failed";
		}
		else{
			this.datalogs = this.datalogs + "Successfully edit merchant: Add Match/Trace" + System.getProperty("line.separator");
			match_trace_status="Success";
		}

		return match_trace_status;


		//##Come back late
		/*if(send_to_host > 0){
			ok = m.sendMatchTrace(merchant_id, case_id, post, "mbbadmin", "00");
			if(ok == false){
				//datalogs= datalogs + "Fail to send match trace" + System.getProperty("line.separator");
				datalogs= datalogs + "Fail to send match trace" + System.getProperty("line.separator")+ m.getMessage() + System.getProperty("line.separator");
				//json_error(m.getMessage(), response);
				//return null;
			}
			else{
				datalogs= datalogs + "Successfully send match trace" + System.getProperty("line.separator");
			}
		}
		*/

	}

	public String create_outlet_detail(TreeMap<String, String> appinfo, String mcc_code, long mid, long cid){
		String outlet_detail_status="";
		TreeMap<String, String> post = new TreeMap<String, String>();
		post.put("merchant_id", Long.toString(mid));
		post.put("case_id", Long.toString(cid));
		post.put("registered_name", appinfo.get("regname"));
		post.put("registered_no", appinfo.get("regno"));
		post.put("trading_name", appinfo.get("trading"));
		post.put("contact_person", appinfo.get("contact"));
		post.put("designation", "");
		post.put("email", appinfo.get("email"));
		post.put("telephone_no", appinfo.get("tel"));
		post.put("fax_no", appinfo.get("fax"));
		post.put("esa_ref_no", appinfo.get("esarefno"));
		post.put("no_of_terminal", "00");
		post.put("terminal_rental_fee", "00");
		post.put("terminal_owner","00");
		post.put("license_no",appinfo.get("license"));
		post.put("license_type", "");
		post.put("state", appinfo.get("state"));
		post.put("issuer", appinfo.get("issuer"));
		post.put("expiry_date", appinfo.get("expdate"));
		post.put("risk_level", "");
		post.put("terminal_deposit_wired", "");
		post.put("terminal_deposit_wireless", "");
		post.put("terminal_rental_deposit_wired", "");
		post.put("terminal_rental_deposit_wireless", "");
		post.put("advance_terminal_rental", "");
		post.put("total_cheque_amt", "");
		post.put("bank_issuer", "");
		post.put("bank_branch", "");
		post.put("cheque_no", "");
		post.put("cheque_date", "");
		post.put("terminal_id", "");
		post.put("terminal_id_no", "");
		post.put("terminal_install_date", "");

		OutletFactory o = new OutletFactory();

		boolean ok = o.newCaseOutlet(post, this.userId);
		if(ok == false){
			this.datalogs = this.datalogs + o.getMessage() + System.getProperty("line.separator");
			outlet_detail_status="Failed";
		}
		else{
			this.datalogs = this.datalogs + "Outlet created: #"+o.getOutletID() + System.getProperty("line.separator");
			outlet_detail_status="Success";
		}


		int case_id = (int) cid;
		int outlet_id = (int)o.getOutletID();

		if(outlet_id > 0){
			ArrayList<CaseOutlet> c_outlets = o.getCaseOutlets(case_id);
			if(c_outlets == null){
				this.datalogs = this.datalogs + o.getMessage() + System.getProperty("line.separator");
			}


			String statement_opt = "";
			String other_info = "";
			String user_code3 = "";

			String mdr = "";
			JSONObject mdr_obj = new JSONObject();

			if(this.count_merchant > 1) {
				statement_opt = "{\"visa_1\":\"By Merchant Portal Service\",\"visa_2\":\"" + appinfo.get("merchantportal1") + "\",\"visa_3\":\"" + appinfo.get("merchantportal2") + "\",\"amex_1\":\"\",\"amex_2\":\"\"}";
				user_code3 = "MP";
			}
			else if(this.count_merchant > 0) {
				statement_opt = "{\"visa_1\":\"By Merchant Portal Service\",\"visa_2\":\"" + appinfo.get("merchantportal1") + "\",\"visa_3\":\"\",\"amex_1\":\"\",\"amex_2\":\"\"}";
				user_code3 = "MP";
			}


			other_info = "{\"officer_code\":\"MX1\",\"user_code_1\":\"\",\"user_code_2\":\"\",\"user_code_3\":\"" + user_code3 + "\",\"chain_merchant\":\"000000000\",\"hierarchy_no\":\"\",\"level\":\"0\",\"servicing_rep\":\"0400-L11\",\"sales_rep\":\"L1023477\",\"level_5\":\"\",\"level_6\":\"\"}";


			for(int k = 1; k <= 490; k++) {
				String mdr_v = "";

				switch(k) {
				case 1:
				case 2:
					mdr_v = "027000000000";
					break;

				case 3:
				case 5:
				case 270:
				case 277:
					mdr_v = "000000000";
					break;

				case 4:
					mdr_v = "05";
					break;

				case 6:
				case 7:
				case 13:
				case 271:
				case 272:
				case 273:
				case 274:
				case 275:
				case 276:
				case 331:
					mdr_v = "01";
					break;

				case 8:
				case 9:
				case 10:
				case 11:
				case 12:
					mdr_v = "07";
					break;

				case 182:
				case 183:
				case 184:
				case 185:
				case 186:
				case 187:
				case 188:
				case 189:
					mdr_v = "99";
					break;

				case 214:
				case 215:
				case 216:
				case 217:
				case 218:
				case 219:
				case 220:
				case 221:
					mdr_v = "0001";
					break;

				case 349:
					mdr_v = "7399";
					break;

				case 355:
				case 356:
				case 357:
				case 358:
				case 359:
				case 360:
					mdr_v = "0";
					break;

				case 361:
				case 362:
				case 363:
				case 364:
				case 365:
				case 366:
					mdr_v = "MST01";
					break;

				case 367:
				case 368:
				case 369:
				case 370:
				case 371:
				case 372:
					mdr_v = "999";
					break;

				case 373:
				case 374:
				case 375:
				case 376:
				case 377:
				case 378:
				case 403:
				case 404:
				case 405:
				case 406:
				case 407:
				case 408:
				case 409:
				case 410:
					mdr_v = "99";
					break;

				case 395:
				case 396:
				case 397:
				case 398:
				case 399:
				case 400:
				case 401:
				case 402:
					mdr_v = "18";
					break;

				case 22:
				case 23:
				case 24:
				case 25:
				case 26:
				case 27:
				case 28:
				case 29:
				case 295:
				case 296:
				case 297:
				case 298:
				case 299:
				case 300:
				case 435:
				case 436:
				case 437:
				case 438:
				case 439:
				case 440:
				case 441:
				case 442:
					mdr_v = mcc_code;
					break;

				case 30:
				case 38:
				case 46:
				case 54:
					mdr_v = appinfo.get("mdr_credit");
					break;

				case 62:
				case 70:
					mdr_v = appinfo.get("mdr_debit");
					break;

				case 307:
					mdr_v = appinfo.get("mdr_amex");
					break;

				default:
					break;
				}

				mdr_obj.put(k, mdr_v);
			}


			if(this.maincsv_ordertype.equals("AT")){
				if(this.maincsv_merchantid.equals("") == false) {
					mdr_obj.put(14, this.maincsv_merchantid);
				}
			}

			if(mdr_obj.isEmpty() == false) {
				mdr = mdr_obj.toJSONString();
			}


			String visa_1 = "";
			String amex_1 = "";

			if(appinfo.get("vc_acc").equals("") == false) {
				visa_1 = "credit_maybank";
			}

			if(appinfo.get("vgiro").equals("") == false) {
				visa_1 = "interbank_giro";
			}

			if(appinfo.get("amex_acc").equals("") == false) {
				amex_1 = "credit_maybank";
			}

			if(appinfo.get("amex_giro").equals("") == false) {
				amex_1 = "interbank_giro";
			}

			TreeMap<String, String> post2 = new TreeMap<String, String>();
			post2.put("payment_info", "{\"cust_1\":\"\",\"cust_2\":\"\",\"cust_3\":\"\",\"visa_1\":\"" + visa_1 + "\",\"visa_2\":\""+ appinfo.get("vc_acc") + "\",\"visa_3\":\"012\",\"visa_4\":\"002\",\"visa_5\":\""+ appinfo.get("vgiro") + "\",\"visa_6\":\"02726014\",\"visa_7\":\"00000\",\"amex_1\":\"" + amex_1 + "\",\"amex_2\":\""+ appinfo.get("amex_acc") + "\",\"amex_3\":\""+ appinfo.get("amex_giro") + "\",\"amex_4\":\""+ appinfo.get("amex_code") + "\",\"amex_5\":\"01001\",\"amex_6\":\"Individual Pay\",\"amex_7\":\"\",\"amex_8\":\"102\",\"amex_9\":\"027000000000000\",\"amex_10\":\"00000\",\"union_pay_1\":\"\",\"ezypay_1\":\"02700000\",\"ezypay_2\":\"00000\",\"mbb_phi_1\":\"10100000\",\"mbb_phi_2\":\"00000\",\"mbb_sg_1\":\"10200000\",\"mbb_sg_2\":\"00000\"}");
			post2.put("statement_opt", statement_opt);
			post2.put("other_info", other_info);
			post2.put("physical_address", "{\"line_1\":\""+appinfo.get("phy_street1")+"\",\"line_2\":\""+appinfo.get("phy_street2")+"\",\"line_3\":\""+appinfo.get("phy_street3")+"\",\"line_4\":\""+appinfo.get("phy_street4")+"\",\"postal_code\":\""+appinfo.get("phy_pcode")+"\",\"city\":\""+appinfo.get("phy_city")+"\",\"region_code\":\""+appinfo.get("phy_rcode")+"\"}");
			post2.put("payment_address", "{\"line_1\":\""+appinfo.get("pay_street1")+"\",\"line_2\":\""+appinfo.get("pay_street2")+"\",\"line_3\":\""+appinfo.get("pay_street3")+"\",\"line_4\":\""+appinfo.get("pay_street4")+"\",\"postal_code\":\""+appinfo.get("pay_pcode")+"\",\"city\":\""+appinfo.get("pay_city")+"\",\"region_code\":\""+appinfo.get("pay_rcode")+"\"}");
			post2.put("correspondence_address", "{\"line_1\":\""+appinfo.get("cor_street1")+"\",\"line_2\":\""+appinfo.get("cor_street2")+"\",\"line_3\":\""+appinfo.get("cor_street3")+"\",\"line_4\":\""+appinfo.get("cor_street4")+"\",\"postal_code\":\""+appinfo.get("cor_pcode")+"\",\"city\":\""+appinfo.get("cor_city")+"\",\"region_code\":\""+appinfo.get("cor_rcode")+"\"}");
			post2.put("mdr", mdr);

			if(this.maincsv_ordertype.equals("AT")){
				if(this.maincsv_merchantid.equals("") == false) {
					post2.put("mid_pos", this.maincsv_merchantid);
				}
			}

			ok = o.editCaseOutlet(case_id, outlet_id, post2, this.userId);
			if(ok == false){
				this.datalogs += o.getMessage() + System.getProperty("line.separator");
				outlet_detail_status="Failed";
			}

			String recom = "{\"rate\":\"\",\"visa_rate\":\"\",\"jcb_rate\":\"\",\"debit_rate\":\"\",\"amex_rate\":\"\",\"trf\":\"\",\"curr_card_sales\":\"\",\"no_of_outlet\":\"\",\"terminal_edc\":[],\"no_of_wired_terminal\":\"\",\"no_of_wireless_terminal\":\"\",\"no_of_mpos_terminal\":\"" + this.maincsv_mfosqty + "\",\"terminal_rental\":[],\"terminal_rental_amount\":\"\",\"terminal_rental_wired\":\"\",\"terminal_rental_wireless\":\"\",\"terminal_rental_acc\":\"\",\"terminal_rental_bank\":\"\",\"min_card_sales\":\"\",\"mbb_ca\":\"\",\"avg_deposit\":\"\",\"avg_credit_balance\":\"\",\"referral\":\"\",\"proven_card_sales\":\"\",\"projected_card_sales\":\"\"}";
			ok = o.editCaseOutletRecom(case_id, outlet_id, recom);
			if(ok == false){
				this.datalogs += o.getMessage() + System.getProperty("line.separator");
				outlet_detail_status="Failed";
			}
		}

		return outlet_detail_status;
	}


	public String getExceptionAsString(Exception e){
		StringWriter errors = new StringWriter();
		e.printStackTrace(new PrintWriter(errors));

		return errors.toString();
	}


	public void appendlogs(String logdata){
		Date dNow = new Date( );
		SimpleDateFormat dformat = new SimpleDateFormat ("yyyy.MM.dd");
		SimpleDateFormat lformat = new SimpleDateFormat ("MMM d, y hh:mm:ss a");
		File logfolder = new File(this.logPath + dformat.format(dNow) + "/");

		boolean b = false;
    	if (!logfolder.exists()) b = logfolder.mkdirs();

		String dir_log = this.logPath + dformat.format(dNow) + "/";

		PrintWriter out = null;

	    try {
			out = new PrintWriter(new BufferedWriter(new FileWriter(dir_log+dformat.format(dNow)+".log", true)));
			//start write content to log file
			out.println(lformat.format(dNow) + " " + MaxisMPOS.class.getName().toString() + System.getProperty("line.separator") + logdata + System.getProperty("line.separator"));

			//After done writing, remember to close!
			out.close();
		} catch (IOException e) {
			//exception handling left as an exercise for the reader
			StringWriter errors = new StringWriter();
			e.printStackTrace(new PrintWriter(errors));
			this.datalogs += "Error IOException:" + System.getProperty("line.separator")+errors.toString()+ System.getProperty("line.separator");
		}


	    //start write content to log file
	    out.println(lformat.format(dNow) + " " + MaxisMPOS.class.getName().toString() + System.getProperty("line.separator") + logdata + System.getProperty("line.separator"));

	    //After done writing, remember to close!
	    out.close();
	}

	public void deleteFile(File f){
		if(f == null) return;

		f.delete();
	}


	public void moveFile(File afile, String fstatus){
    	Date dNow = new Date();
		SimpleDateFormat dformat = new SimpleDateFormat ("yyyy.MM.dd");

		String toDirectory = "";

		if(fstatus.equals("Success")){
    		File sfile = new File(this.successPath + dformat.format(dNow) + "/");
    		if (!sfile.exists()) {
    			sfile.mkdirs();
    		}

    		toDirectory = this.successPath + dformat.format(dNow) + "/";
    	}
    	else if(fstatus.equals("Failed")){
    		File ffile = new File(this.failPath + dformat.format(dNow) + "/");
    		if (!ffile.exists()) {
    			ffile.mkdirs();
    		}

    		toDirectory = this.failPath + dformat.format(dNow) + "/";
    	}
    	else if(fstatus.equals("Error")){
    		File efile = new File(this.errorPath + dformat.format(dNow) + "/");
    		if (!efile.exists()) {
    			efile.mkdirs();
    		}

    		toDirectory = this.errorPath + dformat.format(dNow) + "/";
    	}


		if(toDirectory.equals("")) {
			return;
		}

		String oldFilePath = afile.getAbsolutePath();
		String newFilePath = toDirectory + afile.getName();

		String logstr = "";

		if(afile.renameTo(new File(newFilePath))){
			logstr = "SUCCESS MOVE ==> from " + oldFilePath + " to " + newFilePath + System.getProperty("line.separator");
		} else {
			logstr = "FAILED MOVE ==> from " + oldFilePath + " to " + newFilePath + System.getProperty("line.separator");
		}

		this.datalogs += logstr;
		System.out.println(logstr);
    }

	private String createResponseFolder(){
		   Date dNow = new Date();
		   SimpleDateFormat dformat = new SimpleDateFormat ("yyyy.MM.dd");
		   File resfolder = new File(this.mapResponsePath + dformat.format(dNow) + "/");

		   boolean b = false;
		   if (!resfolder.exists()) {
			   b = resfolder.mkdirs();
		   }

		   return this.mapResponsePath + dformat.format(dNow) + "/";
	}
}
